/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package analisadorSemantico;

import java.util.Set;
import java.util.Stack;
import modelo.ParametroIncompativel;
import modelo.Procedimento;
import modelo.tipos.TipoVariavel;

/**
 *
 * @author DEP
 */
public class VerificacaoDeParametros {

    private Stack<TipoVariavel> pilhaDeParametrosReais;
    private Stack<TipoVariavel> pilhaDeParametrosFormais;
    private int linha;
    private Procedimento procedimento;

    public VerificacaoDeParametros(int linha) {
        this.pilhaDeParametrosReais = new Stack<>();
        this.linha = linha;
    }

    public void setProcedimento(Procedimento procedimento) {
        this.procedimento = procedimento;
        this.pilhaDeParametrosFormais = new Stack<>();
    }

    public void push(TipoVariavel t) {
        pilhaDeParametrosReais.push(t);
    }

    public void avaliar() throws ParametroIncompativel {
        if (procedimento != null) {
            Set<String> chaves = procedimento.getParametros().keySet();
            for (String chave : chaves) {
                if (chave != null) {
                    pilhaDeParametrosFormais.add(procedimento.getParametros().get(chave));
                }
            }

            if (pilhaDeParametrosReais.size() > pilhaDeParametrosFormais.size()) {
                throw new ParametroIncompativel("O número de parâmetros informados na linha " + linha + ", é maior que o declaradao em \"" + procedimento.getNome() + "\".\n");
            } else if (pilhaDeParametrosReais.size() < pilhaDeParametrosFormais.size()) {
                throw new ParametroIncompativel("O número de parâmetros informados na linha " + linha + ", é menor que o declaradao em \"" + procedimento.getNome() + "\".\n");
            } else {
                TipoVariavel tvar1 = null, tvar2 = null;
                while (!pilhaDeParametrosReais.isEmpty() && !pilhaDeParametrosFormais.isEmpty()) {
                    tvar1 = pilhaDeParametrosFormais.pop();
                    tvar2 = pilhaDeParametrosReais.pop();
                    if (tvar1 != tvar2) {
                        throw new ParametroIncompativel("O tipo do parâmetro " + (pilhaDeParametrosReais.size() + 1) + " no subprograma \"" + procedimento.getNome() + "\" na linha " + linha + " não é compatível.\n");
                    }
                }
            }
        }
    }
}
